unit Pop3Thread;

interface
uses
  Classes,IdPOP3,IdMessage,ComCtrls,StrUtils,Dialogs,System.Generics.Collections,MGlobal
  ,System.SysUtils;
type
  TBeginReceiveEvent=procedure(zh:string;msgcount:Integer) of object;
  TReceiveEvent=procedure(zh:string;msgindex:Integer;uid:string;stream:TStream) of object;
  TReceiveEndEvent=procedure(zh:string) of object;
  TPop3Thread=Class(TThread)
  private
    Pop:TIdPop3;
    //fmailzh:tmailzh;
    _zh:string;
    uidlist:TList<string>;
    FOnReceiveMsg: TReceiveMsgEvent;
    FOnReceiveEnd: TReceiveEndEvent;
    FOnReceiveProgress: TReceiveMsgProgressEvent;
    FOnReceiveRaw: TReceiveRawEvent;
    FOnReceive: TReceiveEvent;
    FOnBeginReceive: TBeginReceiveEvent;
    procedure SetOnReceiveMsg(const Value: TReceiveMsgEvent);
    procedure SetOnReceiveEnd(const Value: TReceiveEndEvent);
    procedure SetOnReceiveProgress(const Value: TReceiveMsgProgressEvent);
    procedure SetOnReceiveRaw(const Value: TReceiveRawEvent);
    procedure SetOnReceive(const Value: TReceiveEvent);
    procedure SetOnBeginReceive(const Value: TBeginReceiveEvent);
  protected
    procedure Execute;override;
  public

    subject:string;
    msgsize:Int64;
    status:integer;//0,1 udl,2 receive,3 end
    property OnReceive:TReceiveEvent read FOnReceive write SetOnReceive;
    property OnBeginReceive:TBeginReceiveEvent read FOnBeginReceive write SetOnBeginReceive;

    property OnReceiveEnd:TReceiveEndEvent read FOnReceiveEnd write SetOnReceiveEnd;
   
    Constructor Create(zh:string);
    Destructor  Destroy;override;

    procedure Receive;
    procedure initpop(var _pop:TIdPOP3;var _uid:TList<string>);
  End;


implementation

{ TPop3Thread }


constructor TPop3Thread.Create(zh:string);
begin
  inherited Create(true);
  _zh:=zh;
  FreeOnTerminate :=true;
end;

destructor TPop3Thread.Destroy;
begin
  //Free;
  inherited;

end;

procedure TPop3Thread.Execute;
begin
  inherited;

  try
    Receive;
  finally

  end;

  //if Assigned(FOnReceiveEnd) then
  //  FOnReceiveEnd(_zh);
  //self.Terminate;
    //Pop.Disconnect;
end;

procedure TPop3Thread.initpop(var _pop: TIdPOP3;var _uid:TList<string>);
begin
  pop:=_pop;
  uidlist:=_uid;

end;

procedure TPop3Thread.Receive;
var
  i,n,index: Integer;
  raw:TStringList;
  sl:tstringlist;
  unread:TList<integer>;
  idmsg:tidmessage;
  stream:TMemoryStream;
begin
  try
    if not Terminated then
    begin
      try
      status:=1;
      sl:=TStringList.Create;
      if not pop.Connected then
        pop.Connect;
      status:=2;
      pop.UIDL(sl);
      n:=sl.count;
      unread:=tlist<integer>.create;
      //unreaduid:=tlist<string>.create;
      for i := 0 to n-1 do
      begin
        if not uidlist.Contains(sl[i]) then
        begin
          unread.Add(i);
        end;
      end;
      n:=unread.Count;
      //fmailzh.MsgCount:=msgcount;
      if Assigned(FOnBeginReceive) then
        FOnBeginReceive(_zh,n);
      status:=3;
      for i := 0 to n-1 do
      begin
        if not Terminated then
        begin
        index:=unread[i];

        try
        idmsg:=TIdMessage.Create(pop);
        msgsize:=pop.RetrieveMsgSize(index+1);
        pop.RetrieveHeader(index+1,idmsg);
        subject:=idmsg.Subject;
        //fmailzh.curidmsg:=tidmessage.Create;
        //fmailzh.curidmsg:=idmsg;
          try
          stream:=TMemoryStream.Create;
          Pop.RetrieveRaw(index+1,stream);
          if Assigned(FOnReceive) then
            FOnReceive(_zh,i+1,sl[index],stream);

            //if Assigned(FOnReceiveRaw) then
             // FOnReceiveRaw(zh,sl[index],stream);

          finally
            FreeAndNil(stream);
          end;

        finally
          FreeAndNil(idmsg);
         subject:='';
        end;

        end;
        if Terminated then
          exit;
         //FreeAndNil(fmailzh.curidmsg);
          //raw.Free;
      end;

      finally
        sl.Free;
      end;

    end;
    if Assigned(FOnReceiveEnd) then
      FOnReceiveEnd(_zh);
  except

  end;


end;

procedure TPop3Thread.SetOnBeginReceive(const Value: TBeginReceiveEvent);
begin
  FOnBeginReceive := Value;
end;

procedure TPop3Thread.SetOnReceive(const Value: TReceiveEvent);
begin
  FOnReceive := Value;
end;

procedure TPop3Thread.SetOnReceiveEnd(const Value: TReceiveEndEvent);
begin
  FOnReceiveEnd := Value;
end;

procedure TPop3Thread.SetOnReceiveMsg(const Value: TReceiveMsgEvent);
begin
  FOnReceiveMsg := Value;
end;

procedure TPop3Thread.SetOnReceiveProgress(
  const Value: TReceiveMsgProgressEvent);
begin
  FOnReceiveProgress := Value;
end;

procedure TPop3Thread.SetOnReceiveRaw(const Value: TReceiveRawEvent);
begin
  FOnReceiveRaw := Value;
end;

end.
